package v5

import (
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"math/rand"
	"mindonmap/models"
	"mindonmap/pkgs/e"
	"mindonmap/pkgs/setting"
	"mindonmap/pkgs/util"
	"net/http"
	"sort"
	"strconv"

	jwt "github.com/appleboy/gin-jwt/v2"
	"github.com/gin-contrib/sessions"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"gopkg.in/yaml.v2"

	"net/url"
	"strings"
	"time"
)

type Plan struct {
	PlanId        int     `yaml:"plan_id" json:"plan_id"`
	Name          string  `yaml:"plan_name" json:"plan_name"`
	Price         float64 `yaml:"show_price" json:"show_price"`
	OriginalPrice float64 `yaml:"original_price" json:"original_price"`
	Discount      float64 `yaml:"discount" json:"discount"`
	Credits       int     `yaml:"credits"  json:"credits"`
	Sort          int     `yaml:"sort"  json:"sort"`
	Proportion    int     `yaml:"proportion"  json:"proportion"`
	ProductId     int     `yaml:"product_id" json:"product_id"`
}
type UserDevice struct {
	ID             int       `json:"id"`
	UserId         int       `json:"user_id"`
	UserAccount    string    `json:"user_account"`
	DeviceID       string    `json:"device_id"`
	System         string    `json:"system"`
	DeviceName     string    `json:"device_name"`
	FirstLoginTime time.Time `json:"first_login_time"`
	LastLoginTime  time.Time `json:"last_login_time"`
}

type UserSubscriptions struct {
	ProductID      string `json:"product_id"`
	ProductFeature string `json:"product_feature"`
	Since          string `json:"since"`
	Expire         string `json:"expire"`
}

type UserSubPermission struct {
	Buy           bool   `json:"Buy"`
	Expire        int64  `json:"expire"`
	Expired       bool   `json:"expired"`
	Usertype      int64  `json:"usertype"`
	Feature       string `json:"feature"`
	Nlimits       int    `json:"nodelimits"`
	FreeCreadit   int    `json:"free_creadit"`
	MemberCreadit int    `json:"member_creadit"`
	AddedCreadit  int    `json:"added_creadit"`
	Status        string `json:"status"`
	AllCreadit    int    `json:"all_creadit"`
}

type BenefitStatues struct {
	ProductID string `json:"product_id"`
}

type BenefitCheck struct {
	Types  string `json:"types"`
	Number int    `json:"num"`
	Event  string `json:"Event"`
}

// / 根结构体，包含 subscriptions 数组
type Response struct {
	Subscriptions []Subscription `json:"subscriptions"`
	Debug         []interface{}  `json:"debug"`
	Error         int            `json:"error"`
}

// 订阅信息结构体
type Subscription struct {
	ID               interface{} `json:"id"` // 注意：部分字段为字符串类型
	ProductFeature   interface{} `json:"product_feature"`
	Since            interface{} `json:"since"`
	Expire           interface{} `json:"expire"`
	ExpireEffective  interface{} `json:"expire_effective"`
	TSBenefitUpgrade interface{} `json:"ts_benefit_upgrade"` // 驼峰命名转换（JSON键为下划线风格时需调整标签）
	Benefits         []Benefit   `json:"benefits"`
}

// 权益信息结构体
type Benefit struct {
	Key       string      `json:"key"`
	Type      string      `json:"type"`
	Quota     string      `json:"quota"` // 字符串类型，需转换为整数
	Threshold interface{} `json:"threshold"`
	Limit     interface{} `json:"limit"`
	Upgrade   bool        `json:"upgrade"`
	Usage     int         `json:"usage"`
	Cost      int         `json:"cost"`
}

type Order struct {
	OrderNumber string `json:"order_number"`
	URL         string `json:"url"`
	TSExpire    int    `json:"ts_expire"`
	UrlGateway  string `json:"url_gateway"`
	//Debug []interface{} `json:"debug"`
	Error int `json:"error"`
}
type RequestCheckout struct {
	PlanID   string `json:"plan_id"`
	Language string `json:"language"`
	Gateway  string `json:"gateway"`
}

// 游客下单
func Checkouts(c *gin.Context) {
	var jsons RequestCheckout
	if err := c.BindJSON(&jsons); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": e.INVALID_PARAMS,
			"msg":  e.GetMsg(e.INVALID_PARAMS),
			"data": make(map[string]interface{}),
		})
		return
	}
	randomBytes := make([]byte, 16)
	_, err := rand.Read(randomBytes)
	if err != nil {
		fmt.Println("Error generating random bytes:", err)
		return
	}
	randomString := base64.URLEncoding.EncodeToString(randomBytes)
	randomString = strings.ReplaceAll(randomString, "=", "")

	values := url.Values{}
	values.Add("e_id", randomString)
	values.Add("plan_id", jsons.PlanID)
	values.Add("language", jsons.Language)
	if jsons.Gateway != "" {
		values.Add("gateway", jsons.Gateway)
	} else {
		values.Add("gateway", "3")
	}

	paramsReques := values.Encode()
	baseurl := setting.GetLoginurl() + "/subscription/checkout"

	responseToken, _ := http.Post(baseurl, "application/x-www-form-urlencoded", strings.NewReader(paramsReques))
	defer responseToken.Body.Close()
	body, err := ioutil.ReadAll(responseToken.Body)
	if err != nil {
		fmt.Println(err)
	}
	code := e.SUCCESS
	var data Order
	err = json.Unmarshal(body, &data)
	if err != nil {
		fmt.Println(err)
	}
	if data.Error == 0 {
		url := getURL(data.URL)
		data.URL = url
	}
	c.JSON(http.StatusOK, gin.H{
		"code": code,
		"msg":  "",
		"data": data,
	})
}
func Checkout(c *gin.Context) {
	var jsons RequestCheckout
	if err := c.BindJSON(&jsons); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": e.INVALID_PARAMS,
			"msg":  e.GetMsg(e.INVALID_PARAMS),
			"data": make(map[string]interface{}),
		})
		return
	}
	// // 是否是会员
	// if IsVip(c) {
	// 	c.JSON(http.StatusOK, gin.H{
	// 		"code": e.ERROR_PAY_already_exist,
	// 		"msg":  e.GetMsg(e.ERROR_PAY_already_exist),
	// 		"data": make(map[string]interface{}),
	// 	})
	// 	return
	// }

	params, err := GetLoginUserInfo(c)
	if err != nil {
		return
	}
	paramsStr := fmt.Sprintf("%v", params)

	values := url.Values{}
	values.Add("plan_id", jsons.PlanID)
	values.Add("language", jsons.Language)
	if jsons.Gateway != "" {
		values.Add("gateway", jsons.Gateway)
	} else {
		values.Add("gateway", "3")
	}
	paramsReques := values.Encode()

	v := strings.Join([]string{paramsStr, paramsReques}, "&")

	baseurl := setting.GetLoginurl() + "/subscription/checkout"
	responseToken, _ := http.Post(baseurl, "application/x-www-form-urlencoded", strings.NewReader(v))
	defer responseToken.Body.Close()
	body, err := ioutil.ReadAll(responseToken.Body)
	if err != nil {
		fmt.Println(err)
	}
	code := e.SUCCESS
	var data Order
	err = json.Unmarshal(body, &data)
	if err != nil {
		fmt.Println(err)
	}
	url := getURL(data.URL)
	data.URL = url
	c.JSON(http.StatusOK, gin.H{
		"code": code,
		"msg":  "",
		"data": data,
	})
}

func getURL(url string) string {
	baseurl := url + "?json=1"
	responseToken, _ := http.Get(baseurl)
	defer responseToken.Body.Close()
	body, err := ioutil.ReadAll(responseToken.Body)
	if err != nil {
		fmt.Println(err)
	}
	var data Order
	err = json.Unmarshal(body, &data)
	if err != nil {
		fmt.Println(err)
	}
	return data.URL
}

func PayResult(OrderNumber string, params string) bool {

	paramsStr := fmt.Sprintf("%v", params)

	values := url.Values{}
	values.Add("order_number", OrderNumber)
	paramsReques := values.Encode()

	v := strings.Join([]string{paramsStr, paramsReques}, "&")

	fmt.Println(v)
	baseurl := setting.GetLoginurl() + "/subscription/result"
	responseToken, _ := http.Post(baseurl, "application/x-www-form-urlencoded", strings.NewReader(v))
	defer responseToken.Body.Close()
	body, err := ioutil.ReadAll(responseToken.Body)
	if err != nil {
		fmt.Println(err)
	}
	var data Order
	err = json.Unmarshal(body, &data)
	if err != nil {
		fmt.Println(err)
	}
	if data.Error == 0 {
		return true
	} else {
		return false
	}

}
func OrderAll(c *gin.Context) {
	params, err := GetLoginUserInfo(c)
	if err != nil {
		return
	}
	paramsStr := fmt.Sprintf("%v", params)

	fmt.Println(paramsStr)
	baseurl := setting.GetLoginurl() + "/order/list2"
	responseToken, _ := http.Post(baseurl, "application/x-www-form-urlencoded", strings.NewReader(paramsStr))
	defer responseToken.Body.Close()
	body, err := ioutil.ReadAll(responseToken.Body)
	if err != nil {
		fmt.Println(err)
	}
	code := e.SUCCESS
	var data map[string]interface{}
	err = json.Unmarshal(body, &data)
	if err != nil {
		fmt.Println(err)
	}
	c.JSON(http.StatusOK, gin.H{
		"code": code,
		"msg":  "",
		"data": data,
	})
}
func SubscriptionStatusFB(c *gin.Context) {
	params, err := GetLoginUserInfo(c)
	if err != nil {
		return
	}
	paramsStr := fmt.Sprintf("%v", params)
	fmt.Println(paramsStr)
	baseurl := setting.GetLoginurl() + "/subscription/status"
	responseToken, _ := http.Post(baseurl, "application/x-www-form-urlencoded", strings.NewReader(paramsStr))
	defer responseToken.Body.Close()
	body, err := ioutil.ReadAll(responseToken.Body)
	if err != nil {
		fmt.Println(err)
	}
	//var data UserSubscriptions
	var data map[string]interface{}
	var subscriptions models.UserSubscriptions
	err = json.Unmarshal([]byte(body), &data)
	if err != nil {
		fmt.Println(err)
	}

	subs, ok := data["subscriptions"].([]interface{})

	if !ok {
		c.JSON(http.StatusOK, gin.H{
			"code": e.SUCCESS,
			"msg":  data["subscriptions"],
			"data": data,
		})
		return
	}

	size := len(subs)
	if size != 0 {
		var expire = 0
		for i := range subs {
			s := subs[i].(map[string]interface{})
			// 获取产品id 2 win版本订阅
			// 获取过期时间
			var expireData, _ = strconv.Atoi(s["expire"].(string))
			if s["product_id"].(string) == "2" && expireData > expire {
				expire = expireData
				pid, _ := strconv.Atoi(s["product_id"].(string))
				subscriptions = models.UserSubscriptions{
					ProductID:      pid,
					ProductFeature: s["product_feature"].(string),
					Since:          s["since"].(string),
					Expire:         s["expire"].(string),
				}
			}
			// // 全部版本product_id 2,3
			//subscriptions = append(subscriptions, UserSubscriptions{
			//	ProductID:      s["product_id"].(string),
			//	ProductFeature: s["product_feature"].(string),
			//	Since:          s["since"].(string),
			//	Expire:         s["expire"].(string),
			//})
		}

		names := []string{"t_id", "e_id"}
		paramsRes := util.GetParams(paramsStr, names)
		fmt.Println(paramsRes["t_id"])
		var tid, _ = strconv.Atoi(paramsRes["t_id"])
		subscriptions.UserId = tid

		// 存储订阅信息
		models.EditUserSub(tid, 2, subscriptions)
	}
	c.JSON(http.StatusOK, gin.H{
		"code": e.SUCCESS,
		"msg":  "",
		"data": subscriptions,
	})

}

func SubscriptionStatus(c *gin.Context, Urlstr string) {
	var params string
	if len(Urlstr) == 0 {
		res, err := GetLoginUserInfo(c)
		if err != nil {
			return
		}
		params = res
	} else {
		params = Urlstr
	}

	paramsStr := fmt.Sprintf("%v", params)
	baseurl := setting.GetLoginurl() + "/subscription/status"
	responseToken, _ := http.Post(baseurl, "application/x-www-form-urlencoded", strings.NewReader(paramsStr))

	body, err := ioutil.ReadAll(responseToken.Body)
	defer responseToken.Body.Close()
	if err != nil {
		fmt.Println(err)
		return
	}

	names := []string{"t_id", "e_id"}
	paramsRes := util.GetParams(paramsStr, names)
	var tid, _ = strconv.Atoi(paramsRes["t_id"])

	baseurl2 := setting.GetLoginurl() + "/benefit/status"
	values := url.Values{}
	values.Add("product_id", "2")
	values.Add("all", "1")
	paramsRequest := values.Encode()
	v := strings.Join([]string{paramsStr, paramsRequest}, "&")
	responseToken2, _ := http.Post(baseurl2, "application/x-www-form-urlencoded", strings.NewReader(v))
	body2, err := ioutil.ReadAll(responseToken2.Body)
	defer responseToken2.Body.Close()
	var resp Response
	if err := json.Unmarshal([]byte(body2), &resp); err != nil {
		fmt.Printf("解析错误: %v\n", err)
		return
	}
	// 执行会员状态和点数检查
	free_creadit, member_creadit, added_creadit := SumCredit(resp, tid)

	//var data UserSubscriptions
	var data map[string]interface{}
	var subscriptions models.UserSubscriptions
	err = json.Unmarshal([]byte(body), &data)
	if err != nil {
		fmt.Println("SubscriptionStatus:", Urlstr)
		fmt.Println("SubscriptionStatus:", err)
		return
	}
	subs, _ := data["subscriptions"].([]interface{})
	size := len(subs)
	if size != 0 {
		var expire = 0
		var ids = 0
		for i := range subs {
			s := subs[i].(map[string]interface{})
			// 获取产品id 2 win版本订阅
			// 获取待过期时间最久的
			var expireData, _ = strconv.Atoi(s["expire"].(string))
			if s["product_id"].(string) == "2" && expireData > expire {
				expire = expireData
				pid, _ := strconv.Atoi(s["product_id"].(string))
				subscriptions = models.UserSubscriptions{
					ProductID:      pid,
					ProductFeature: s["product_feature"].(string),
					Since:          s["since"].(string),
					Expire:         s["expire"].(string),
				}
			}
			var product_feature, _ = strconv.Atoi(s["product_feature"].(string))
			if s["product_id"].(string) == "2" && product_feature > ids && product_feature < 14 {
				ids = product_feature
				subscriptions.ProductFeature = strconv.Itoa(ids)
			}
			// // 全部版本product_id 2,3
			//subscriptions = append(subscriptions, UserSubscriptions{
			//	ProductID:      s["product_id"].(string),
			//	ProductFeature: s["product_feature"].(string),
			//	Since:          s["since"].(string),
			//	Expire:         s["expire"].(string),
			//})
		}
		// fmt.Println("订阅信息::", subscriptions)
		// 存储订阅信息
		models.EditUserSub(tid, 2, subscriptions)
	}
	// fmt.Println("ssssss", free_creadit)
	models.UpdateUserLog(tid, free_creadit, member_creadit, added_creadit)
}

// 获取plan_id数组
func GetPlanIDs() ([]int, error) {
	yamlFile, err := ioutil.ReadFile("conf/v5_plans.yaml")
	if err != nil {
		return nil, fmt.Errorf("读取YAML文件失败: %w", err)
	}

	var plans []Plan
	err = yaml.Unmarshal(yamlFile, &plans)
	if err != nil {
		return nil, fmt.Errorf("解析YAML失败: %w", err)
	}

	planIDs := make([]int, 0, len(plans))
	for _, plan := range plans {
		planIDs = append(planIDs, plan.PlanId)
	}
	return planIDs, nil
}

// 权益扣除逻辑
func ConsumptionRights(c *gin.Context, taskId string, cost int, user_id int) (bool, int) {
	params, err := GetLoginUserInfo(c)
	if err != nil {
		return false, 0
	}

	userSub := models.GetUserLog(user_id)
	allToken := userSub.FreeCreadit + userSub.MemberCreadit + userSub.AddedCreadit

	if allToken <= 0 || cost <= 0 {
		return false, 0
	}

	remainingCost := cost
	success := true

	// 定义扣款类型和余额的映射
	creditTypes := []struct {
		name   string
		amount *int
	}{
		{"free", &userSub.FreeCreadit},
		{"member", &userSub.MemberCreadit},
		{"added", &userSub.AddedCreadit},
	}

	// 按顺序处理不同类型的点数
	for _, creditType := range creditTypes {
		if remainingCost <= 0 || *creditType.amount <= 0 {
			continue
		}

		// 计算本次扣除的金额
		deductAmount := *creditType.amount

		if deductAmount > remainingCost {
			deductAmount = remainingCost
		}
		fmt.Println("扣除点数", deductAmount)

		// // 准备请求参数
		values := url.Values{}
		values.Add("product_id", "2")
		usage := uuid.New().String()
		benefitData := map[string]interface{}{
			"key":   "credit",
			"usage": usage,
			"cost":  deductAmount,
		}
		if creditType.name == "free" {
			benefitData["target_subscription_id"] = "0"
		}
		fmt.Println(benefitData)
		// 添加多维参数
		for key, val := range benefitData {
			values.Add(fmt.Sprintf("benefits[0][%s]", key), fmt.Sprintf("%v", val))
		}

		// 合并其他参数
		paramsStr := fmt.Sprintf("%v", params)
		paramsRequest := values.Encode()
		v := strings.Join([]string{paramsStr, paramsRequest}, "&")

		// 发送请求
		baseurl := setting.GetLoginurl() + "/benefit/charge/apply5"
		responseToken, err := http.Post(baseurl, "application/x-www-form-urlencoded,Authorization:Bearer:"+"e74456f402982e312b81b329a306db088172a954d72ba89e05761ea3d0b6cbd4", strings.NewReader(v))
		if err != nil {
			fmt.Println("Request error:", err)
			success = false
			break
		}

		body, err := ioutil.ReadAll(responseToken.Body)
		if err != nil {
			fmt.Println("Read response error:", err)
			success = false
			responseToken.Body.Close()
			break
		}

		var datas map[string]interface{}
		err = json.Unmarshal(body, &datas)
		if err != nil {
			fmt.Println("JSON unmarshal error:", err)
			success = false
		}
		responseToken.Body.Close()

		// 记录信用日志
		creaditData := models.CreaditLog{
			UserId:     user_id,
			Cost:       deductAmount,
			TaskId:     usage,
			Createtime: time.Now().Unix(),
			Content:    fmt.Sprintf("%v", datas),
		}
		models.AddCreadit(creaditData)

		// 更新剩余金额和剩余费用
		*creditType.amount -= deductAmount
		remainingCost -= deductAmount
		fmt.Println(datas["error"])
		fmt.Println(remainingCost)
		// // 如果请求失败，终止循环
		// if datas["error"] != 0 {
		// 	success = false
		// 	break
		// }
	}

	return success, remainingCost
}

// 查看获取权益信息
func Getinterests(c *gin.Context, user_id int) (bool, int) {

	params, err := GetLoginUserInfo(c)
	if err != nil {
		return false, 0
	}
	paramsStr := fmt.Sprintf("%v", params)

	baseurl := setting.GetLoginurl() + "/benefit/status"
	values := url.Values{}
	values.Add("product_id", "2")
	values.Add("all", "1")
	paramsRequest := values.Encode()
	v := strings.Join([]string{paramsStr, paramsRequest}, "&")
	responseToken, _ := http.Post(baseurl, "application/x-www-form-urlencoded", strings.NewReader(v))
	body, err := ioutil.ReadAll(responseToken.Body)
	if err != nil {
		fmt.Println(err)
	}
	defer responseToken.Body.Close()
	// 解析JSON
	var resp Response
	if err := json.Unmarshal([]byte(body), &resp); err != nil {
		fmt.Printf("解析错误: %v\n", err)
		return false, 0
	}

	// 执行会员状态和点数检查
	resultCode := checkMemberAndCredit(resp, user_id)
	if resultCode == 0 {
		return true, 0
	}
	fmt.Printf("最终返回状态码: %d\n", resultCode)
	return false, resultCode
}

func SumCredit(resp Response, user_id int) (num1 int, num2 int, num3 int) {
	now := time.Now().Unix()
	// 定义产品ID分组（注意使用字符串类型，与JSON中的字段匹配）
	comboProductIDs := map[string]bool{"1": true, "2": true, "12": true, "13": true, "19": true, "20": true, "21": true}
	creditProductIDs := map[string]bool{"14": true, "15": true, "16": true, "17": true, "18": true}

	// // 定义点数
	free_creadit := 0
	member_creadit := 0
	added_creadit := 0

	// 1. 处理免费用户的Creadit配额
	freeSub := findSubscriptionByProductFeature(resp.Subscriptions, "0")
	if freeSub != nil {
		freeCredit := getCreditQuota(freeSub.Benefits)
		if freeCredit > 0 {
			free_creadit += freeCredit
		}
	}
	// 2. 判断是否为会员（存在未过期的套餐产品）
	validComboSubs := filterValidSubscriptions(resp.Subscriptions, comboProductIDs, now)
	if len(validComboSubs) > 0 {
		// 检查所有有效套餐的点数
		for _, sub := range validComboSubs {
			quota := getCreditQuota(sub.Benefits)
			if quota > 0 {
				member_creadit += quota
			}
		}
	}

	// 会员检查是否存在增值套餐
	validCreditSubs1 := filterValidSubscriptions_z(resp.Subscriptions, creditProductIDs, now)
	// fmt.Println("validCreditSubs1", len(validCreditSubs1))
	if len(validCreditSubs1) > 0 {
		// 存在有效增值产品，检查点数
		for _, sub := range validCreditSubs1 {
			quota := getCreditQuota(sub.Benefits)
			if quota > 0 {
				added_creadit += quota
			}
		}
	}
	return free_creadit, member_creadit, added_creadit
}

// 检查会员状态和点数配额
func checkMemberAndCredit(resp Response, user_id int) int {
	now := time.Now().Unix()

	// 定义产品ID分组（注意使用字符串类型，与JSON中的字段匹配）
	comboProductIDs := map[string]bool{"1": true, "2": true, "12": true, "13": true, "19": true, "20": true, "21": true}
	creditProductIDs := map[string]bool{"14": true, "15": true, "16": true, "17": true, "18": true}

	// 定义点数
	// free_creadit := 0
	// member_creadit :=0
	// added_creadit :=0
	// code :=0

	// 1. 处理免费用户的Creadit配额
	freeSub := findSubscriptionByProductFeature(resp.Subscriptions, "0")
	if freeSub != nil {
		freeCredit := getCreditQuota(freeSub.Benefits)
		if freeCredit > 0 {
			return 0 // 自定义状态码：免费用户且点数充足
		}
	}
	// 2. 判断是否为会员（存在未过期的套餐产品）
	validComboSubs := filterValidSubscriptions(resp.Subscriptions, comboProductIDs, now)
	if len(validComboSubs) > 0 {
		// 会员逻辑：按到期时间排序，优先使用快到期的套餐
		sort.Slice(validComboSubs, func(i, j int) bool {
			exprice_i := getIdAsString(validComboSubs[i].Expire)
			exprice_j := getIdAsString(validComboSubs[j].Expire)
			expireI, _ := strconv.ParseInt(exprice_i, 10, 64)
			expireJ, _ := strconv.ParseInt(exprice_j, 10, 64)
			return expireI < expireJ // 快到期的在前
		})

		// 检查所有有效套餐的点数
		for _, sub := range validComboSubs {
			quota := getCreditQuota(sub.Benefits)
			if quota > 0 {
				// fmt.Println("会员有效套餐点数充足，正常使用::", quota)
				return 0 // 自定义状态码：会员且点数充足
			}
		}
		// 会员检查是否存在增值套餐
		validCreditSubs1 := filterValidSubscriptions_z(resp.Subscriptions, creditProductIDs, now)
		if len(validCreditSubs1) > 0 {
			// 存在有效增值产品，检查点数
			for _, sub := range validCreditSubs1 {
				quota := getCreditQuota(sub.Benefits)
				if quota > 0 {
					// fmt.Println("会员有效增值产品点数充足")
					return 0
				}
			}
		}
		// 所有套餐点数为0
		// fmt.Println("会员但所有点数为0")
		return 40002 // 状态码40002：会员但点数不足
	}
	// 3. 非会员逻辑：检查增值产品（14-18）
	validCreditSubs := filterValidSubscriptions(resp.Subscriptions, creditProductIDs, now)
	if len(validCreditSubs) > 0 {
		// 存在有效增值产品，检查点数
		for _, sub := range validCreditSubs {
			quota := getCreditQuota(sub.Benefits)
			if quota > 0 {
				// fmt.Println("非会员但增值产品点数充足")
				return 40003 // 状态码40003：非会员但点数充足
			}
		}
		// 增值产品均无点数
		// fmt.Println("非会员且增值产品点数为0")
		return 40004 // 状态码1：非会员且点数不足
	}
	// 4. 无套餐且无增值产品
	// fmt.Println("非会员且无有效产品")
	return 40004 // 状态码3：非会员且无有效产品
}

// 非float64类型使用默认转换
func convertToString(value interface{}) string {
	if f, ok := value.(float64); ok {
		return strconv.FormatFloat(f, 'f', -1, 64)
	}
	return fmt.Sprintf("%v", value)
}

// 辅助函数：根据产品ID查找订阅
func findSubscriptionByProductFeature(subs []Subscription, productFeature string) *Subscription {
	for i := range subs {
		t := convertToString(subs[i].ProductFeature)
		t1 := convertToString(productFeature)
		if t == t1 {
			return &subs[i]
		}
	}
	return nil
}

// 辅助函数：过滤有效订阅（未过期且属于目标产品组）
func filterValidSubscriptions(subs []Subscription, productIDs map[string]bool, now int64) []Subscription {
	var valid []Subscription
	for _, sub := range subs {
		expire_time := getIdAsString(sub.Expire)

		// 转换Expire字符串为int64进行比较
		expire, err := strconv.ParseInt(expire_time, 10, 64)
		if err != nil || expire == 0 {
			continue // 跳过解析失败或过期时间为0的订阅
		}
		id := getIdAsString(sub.ProductFeature)
		if productIDs[id] && expire > now {
			valid = append(valid, sub)
		}
	}
	return valid
}

// 辅助函数：过滤有效订阅（未过期且属于目标产品组）
func filterValidSubscriptions_z(subs []Subscription, productIDs map[string]bool, now int64) []Subscription {
	var valid []Subscription
	for _, sub := range subs {

		id := getIdAsString(sub.ProductFeature)
		if productIDs[id] {
			valid = append(valid, sub)
		}
	}
	return valid
}

// 辅助函数：获取ID的字符串表示
func getIdAsString(id interface{}) string {
	switch v := id.(type) {
	case string:
		return v
	case float64:
		return strconv.FormatFloat(v, 'f', 0, 64)
	default:
		return ""
	}
}

// 辅助函数：获取Creadit配额（字符串转整数）
func getCreditQuota(benefits []Benefit) int {
	for _, b := range benefits {
		if b.Key == "credit" {
			quota, err := strconv.Atoi(b.Quota)
			cost := b.Cost
			use := quota - cost
			if err != nil {
				return 0 // 解析失败返回0
			}
			if use > 0 {
				return use
			} else {
				return 0
			}
		}
	}
	return 0 // 未找到credit权益返回0
}
func BenefitStatus(c *gin.Context) {
	var jsons BenefitStatues
	if err := c.BindJSON(&jsons); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": e.INVALID_PARAMS,
			"msg":  e.GetMsg(e.INVALID_PARAMS),
			"data": make(map[string]interface{}),
		})
		return
	}

	params, err := GetLoginUserInfo(c)
	if err != nil {
		return
	}
	paramsStr := fmt.Sprintf("%v", params)

	values := url.Values{}
	values.Add("product_id", jsons.ProductID)
	paramsRequest := values.Encode()

	v := strings.Join([]string{paramsStr, paramsRequest}, "&")

	baseurl := setting.GetLoginurl() + "/benefit/status"
	responseToken, _ := http.Post(baseurl, "application/x-www-form-urlencoded", strings.NewReader(v))
	defer responseToken.Body.Close()
	body, err := ioutil.ReadAll(responseToken.Body)
	if err != nil {
		fmt.Println(err)
	}
	code := e.SUCCESS
	var data map[string]interface{}
	err = json.Unmarshal(body, &data)
	if err != nil {
		fmt.Println(err)
	}
	c.JSON(http.StatusOK, gin.H{
		"code": code,
		"msg":  "",
		"data": data,
	})
}

func PackageInfo(c *gin.Context) {
	yamlFile, err := ioutil.ReadFile("conf/v5_plans.yaml")
	if err != nil {
		fmt.Println(err)
	}
	// 解析YAML为Plan切片
	var plans []Plan
	err = yaml.Unmarshal(yamlFile, &plans)
	if err != nil {
		fmt.Println(err)
	}

	c.JSON(http.StatusOK, gin.H{
		"code": e.SUCCESS,
		"msg":  "",
		"data": plans,
	})
}

// 登录初始化
func IsVip(c *gin.Context) bool {
	Userid, _ := GetUserID(c)
	var UserSub = models.GetUserSub(Userid)
	var Expires, _ = strconv.ParseInt(UserSub.Expire, 10, 64)
	expire := time.Unix(Expires, 0)
	now := time.Now().UTC()
	// 判断订阅是否过期，返回是否是 vip 会员
	if expire.After(now) {
		return true
	} else {
		return false
	}
}

// 支付成功
func BuySuccessful(c *gin.Context) {
	var jsons Order
	if err := c.BindJSON(&jsons); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": e.INVALID_PARAMS,
			"msg":  e.GetMsg(e.INVALID_PARAMS),
			"data": make(map[string]interface{}),
		})
		return
	}

	params, err := GetLoginUserInfo(c)
	if err != nil {
		return
	}
	// 查询订单支付
	var res = PayResult(jsons.OrderNumber, params)
	fmt.Println(res)
	usertype := "1"
	if res {
		//支付成功,更新订阅
		SubscriptionStatus(c, "")
		// 调用 IsVip(c)
		usertype = "2"
	}

	code := e.SUCCESS
	data := make(map[string]interface{})
	data["usertype"] = usertype
	jsonStr, err := json.Marshal(data)
	if err != nil {
		fmt.Println(err)
	}

	json.Unmarshal(jsonStr, &data)
	c.JSON(http.StatusOK, gin.H{
		"code": code,
		"msg":  "",
		"data": data,
	})
}

func IsBuy(c *gin.Context) {
	Userid, err := GetUserID(c)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": e.ERROR_AUTH_CHECK_TOKEN_TIMEOUT,
			"msg":  e.GetMsg(e.ERROR_AUTH_CHECK_TOKEN_TIMEOUT),
			"data": make(map[string]interface{}),
		})
		return
	}
	SubscriptionStatus(c, "")               // 更新订阅信息
	var UserSub = models.GetUserSub(Userid) // 获取订阅信息
	usertype := "1"
	expired := "true"
	buy := "false"
	if UserSub.ID > 0 {
		buy = "true"

		var Expires, _ = strconv.ParseInt(UserSub.Expire, 10, 64)
		expire := time.Unix(Expires, 0)
		now := time.Now().UTC()

		// 判断订阅是否过期
		if expire.After(now) {
			// 未过期
			usertype = "2"
			expired = "false"
		} else {
			usertype = "1"
			expired = "true"
		}
	} else {
		buy = "false"
		expired = "false"
	}
	// 查库
	// 是否购买过，是否过期；
	pc := NewPrivilegeController()
	code := e.SUCCESS
	var data UserSubPermission
	var Feature string
	var Status string
	Status = ""
	Feature = ""
	if UserSub.ProductFeature == "1" || UserSub.ProductFeature == "12" {
		Feature = "Monthly"
	}
	if UserSub.ProductFeature == "2" || UserSub.ProductFeature == "13" {
		Feature = "Annually"
	}
	if UserSub.ProductFeature == "1" || UserSub.ProductFeature == "2" {
		Status = "Pro"
	}
	if UserSub.ProductFeature == "12" || UserSub.ProductFeature == "13" {
		Status = "Max"
	}
	if UserSub.ProductFeature == "19" {
		Status = "Pro"
		Feature = "MonthlyPro"
	}
	if UserSub.ProductFeature == "20" {
		Status = "Pro"
		Feature = "AnnualPro"
	}
	if UserSub.ProductFeature == "21" {
		Status = "Pro"
		Feature = "3YearPlan"
	}

	data.Usertype, _ = strconv.ParseInt(usertype, 10, 64)
	data.Buy, _ = strconv.ParseBool(buy)
	data.Expired, _ = strconv.ParseBool(expired)
	data.Expire, _ = strconv.ParseInt(UserSub.Expire, 10, 64)
	data.Feature = Feature
	data.Status = Status
	data.Nlimits = pc.MindNodeLimit["free"]
	var UserResult = models.GetUserLog(Userid)
	data.FreeCreadit = UserResult.FreeCreadit
	data.MemberCreadit = UserResult.MemberCreadit
	data.AddedCreadit = UserResult.AddedCreadit
	data.AllCreadit = UserResult.AllCreadit
	jsonStr, _ := json.Marshal(data)
	json.Unmarshal(jsonStr, &data)
	c.JSON(http.StatusOK, gin.H{
		"code": code,
		"msg":  "",
		"data": data,
	})

}

// 用户文件总数
func MindMapTotal(userid int) int {
	var total = models.GetMindMapTotalV5(userid)
	return total.Total
}
func GetLoginUserInfo(c *gin.Context) (string, error) {
	claims := jwt.ExtractClaims(c)
	fmt.Println(claims)
	_, ok := claims["token"].(string)
	if !ok {
		c.JSON(http.StatusOK, gin.H{
			"code": e.ERROR_AUTH_CHECK_TOKEN_TIMEOUT,
			"msg":  e.GetMsg(e.ERROR_AUTH_CHECK_TOKEN_TIMEOUT),
			"data": make(map[string]interface{}),
		})
		return "", errors.New(e.GetMsg(e.ERROR_AUTH_CHECK_TOKEN_TIMEOUT))
	}

	params := claims["token"].(string)

	return params, nil
}
func GetUserID(c *gin.Context) (int, error) {
	errmsg := errors.New("not found")
	claims := jwt.ExtractClaims(c)

	// fmt.Println("claims:", claims)

	id, ok := claims["userId"].(string)
	if !ok {
		return 0, errmsg
	}
	var tid, err = strconv.Atoi(id)
	if tid < 1 || err != nil {
		return 0, errmsg
	}
	return tid, nil
}

func MindMapTotals(c *gin.Context) {
	Userid, err := GetUserID(c)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": e.ERROR_AUTH_CHECK_TOKEN_TIMEOUT,
			"msg":  e.GetMsg(e.ERROR_AUTH_CHECK_TOKEN_TIMEOUT),
			"data": make(map[string]interface{}),
		})
		return
	}
	var total = MindMapTotal(Userid)

	var isvip = IsVip(c)
	var tuser string
	if isvip {
		tuser = "vip"
	} else {
		tuser = "free"
	}
	pc := NewPrivilegeController()

	data := make(map[string]interface{})
	data["numerator"] = total
	data["denominator"] = pc.PrivilegeConfig.CloudStorageLimit[tuser]
	jsonStr, _ := json.Marshal(data)
	json.Unmarshal(jsonStr, &data)

	c.JSON(http.StatusOK, gin.H{
		"code": e.SUCCESS,
		"msg":  e.GetMsg(e.SUCCESS),
		"data": data,
	})

}
func Exportcheck(c *gin.Context) {

	var jsons BenefitCheck
	if err := c.BindJSON(&jsons); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": e.INVALID_PARAMS,
			"msg":  e.GetMsg(e.INVALID_PARAMS),
			"data": make(map[string]interface{}),
		})
		return
	}

	Userid, err := GetUserID(c)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": e.ERROR_AUTH_CHECK_TOKEN_TIMEOUT,
			"msg":  e.GetMsg(e.ERROR_AUTH_CHECK_TOKEN_TIMEOUT),
			"data": make(map[string]interface{}),
		})
		return
	}
	var total = MindMapTotal(Userid)
	pc := NewPrivilegeController()
	var isvip = IsVip(c)
	var typeuser string
	var CheckPriv bool
	if isvip {
		typeuser = "vip"
	} else {
		typeuser = "free"
	}
	switch jsons.Types {
	case "storage_limit":
		CheckPriv = pc.CheckPrivilege(typeuser, "cloud_storage_limit", total)
	case "mind_node":
		CheckPriv = pc.CheckPrivilege(typeuser, "mind_node", jsons.Number)
	case "export_formats":
		CheckPriv = pc.CheckPrivilege(typeuser, "export_formats", 0, jsons.Event)
	case "watermark":
		CheckPriv = pc.CheckPrivilege(typeuser, "watermark", 0)
	}

	if !CheckPriv {
		c.JSON(http.StatusOK, gin.H{
			"code": e.ERROR_AUTH_PERMISSION,
			"msg":  e.GetMsg(e.ERROR_AUTH_PERMISSION),
			"data": make(map[string]interface{}),
		})
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"code": e.SUCCESS,
		"msg":  e.GetMsg(e.SUCCESS),
		"data": CheckPriv,
	})
}

// 权益统计
func statistics(c *gin.Context) {

	//pc := NewPrivilegeController()

	// 修改free用户的云存储限制为10G:
	//pc.CloudStorageLimit["free"] = 10
	//pc.ExportFormats["vip"] = append(pc.ExportFormats["vip"], "png") //允许vip用户导出PNG格式:
	//禁止free用户添加水印:
	//pc.Watermark["free"] = false

	// 验证
	//fmt.Println(pc.CheckPrivilege("free", "export_formats", 0,"svg"))

	// 统计用户类型，查询订阅是否到期，按最久的时间；

	// 统计历史版本数

	// 统计文件个数

	// 导出权益对象

	session := sessions.Default(c)
	getUserInfo := session.Get("userdata")
	paramsStr := fmt.Sprintf("%v", getUserInfo)
	//s := "t_id=37&e_id=04ac70f4ab9cb83dc1a41c82fa831691&token=xxx"
	names := []string{"t_id", "e_id"}
	params := util.GetParams(paramsStr, names)

	//tid := params["t_id"]  // 37
	//eid := params["e_id"]  // 04ac70f4ab9cb83dc1a41c82fa831691
	_, ok := params["token"] // false,未获取token的参数

	//jsonStr := pc.ExportConfig()
	//fmt.Println(jsonStr)
	fmt.Println(ok)

}
func MyBenefit(c *gin.Context) {
	var jsons BenefitStatues
	if err := c.BindJSON(&jsons); err != nil {
		c.JSON(http.StatusOK, gin.H{
			"code": e.INVALID_PARAMS,
			"msg":  e.GetMsg(e.INVALID_PARAMS),
			"data": make(map[string]interface{}),
		})
		return
	}

	session := sessions.Default(c)
	params := session.Get("userdata")
	paramsStr := fmt.Sprintf("%v", params)

	values := url.Values{}
	values.Add("product_id", jsons.ProductID)
	paramsRequest := values.Encode()

	v := strings.Join([]string{paramsStr, paramsRequest}, "&")

	fmt.Println(v)
	baseurl := setting.GetLoginurl() + "/benefit/status"
	responseToken, _ := http.Post(baseurl, "application/x-www-form-urlencoded", strings.NewReader(v))
	defer responseToken.Body.Close()
	body, err := ioutil.ReadAll(responseToken.Body)
	if err != nil {
		fmt.Println(err)
	}
	code := e.SUCCESS
	var data map[string]interface{}
	err = json.Unmarshal(body, &data)
	if err != nil {
		fmt.Println(err)
	}
	c.JSON(http.StatusOK, gin.H{
		"code": code,
		"msg":  "",
		"data": data,
	})
}
